package day21;
/**
主要回顾：装饰者设计模式

继续实现增强类：
	优点：代码结构清晰，实现简单
	缺点：对于每一个需要增强的类都要创建具体的子类来帮助其实现增强，导致继承体系庞大

装饰模式实现的的增强类：
	优点：内部可以通过多态技术对多个需要增强的类进行增强
	缺点：需要内部通过多态技术维护需要增强的类的实例，使代码变复杂了

增强一个类的功能，而且还可以让这些装饰类相互装饰
装饰者设计模式步骤：
	1. 在装饰类的内部维护一个被装饰类的引用
	2. 让装饰类继承自同一个父类或者父接口(本质上是多态的应用)，以便它们可以相互装饰

 */
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;




//带行号的 readLine() 方法，如果需要不同，则需要不同的类
class BufferedLineNum extends BufferedReader{
	int count = 1;

	public BufferedLineNum(Reader in) {
		super(in);
	}
	
	@Override
	public String readLine() throws IOException {
		String line = super.readLine();
		if (line != null) {
			line = count + " " + line;
			count++;
		}
		
		return line;
	}
}

class LineNum extends BufferedReader{	//继续同一父类是为了使用多态
	BufferedReader bReader;
	int lineNum = 1;
	public LineNum(BufferedReader bReader) {
		super(bReader);		//BufferedReader 没有无参的构造方法，需要满足一下它。
		this.bReader = bReader;
	}
	
	public String readLine() throws IOException {
		String line = bReader.readLine();
		if (line != null) {
			line = lineNum + " " + line;
			lineNum++;
		}
		return line;
	}
}

class LineSemi extends BufferedReader{
	BufferedReader bReader;

	public LineSemi(BufferedReader bReader) {
		super(bReader);
		this.bReader = bReader;
	}
	
	public String readLine() throws IOException {
		String line = bReader.readLine();
		if (line != null) {
			line = line + ";";
		}
		return line;
	}
}

class LineQuo{
	BufferedReader bReader;

	public LineQuo(BufferedReader bReader) {
		this.bReader = bReader;
	}
	
	public String readLine() throws IOException {
		String line = bReader.readLine();
		if (line != null) {
			line = "\"" + line + "\"";
		}
		return line;
	}
}

public class DecoratorPattern {

	public static void main(String[] args) throws IOException {
//		testBufferedLineNum();	//通过继续方式实现带行号的readLin()
//		testLineNum();	//带行号的行
//		testLineSemi();	//带分号的行
//		testNumSemi();	//带行号与分号的行
		testNumSemiQuo();	//带行号、分号与双引号的行
	}

	@SuppressWarnings("unused")
	private static void testBufferedLineNum() throws IOException {
		File file = new File("users.txt");
		FileReader fileReader = new FileReader(file);
		BufferedLineNum bNum = new BufferedLineNum(fileReader);
		String line = null;
		while ((line = bNum.readLine()) != null) {
			System.out.println(line);
		}
		bNum.close();
	}

	public static void testLineNum() throws IOException {
		BufferedReader bReader = new BufferedReader(new FileReader("users.txt"));
		LineNum lineNum = new LineNum(bReader);
		String line = null;
		while ((line = lineNum.readLine()) != null) {
			System.out.println(line);
		}
		lineNum.close();
	}
	
	public static void testLineSemi() throws IOException {
		BufferedReader bReader = new BufferedReader(new FileReader("users.txt"));
		LineSemi lineSemi = new LineSemi(bReader);
		String line = null;
		while ((line = lineSemi.readLine()) != null) {
			System.out.println(line);
		}
		lineSemi.close();
	}
	
	public static void testNumSemi() throws IOException {
		BufferedReader bReader = new BufferedReader(new FileReader("users.txt"));
		LineNum lineNum = new LineNum(bReader);
		LineSemi lineSemi = new LineSemi(lineNum);
		String line = null;
		while ((line = lineSemi.readLine()) != null) {
			System.out.println(line);
		}
		lineSemi.close();
	}
	
	public static void testNumSemiQuo() throws IOException {
		BufferedReader bReader = new BufferedReader(new FileReader("users.txt"));
		LineNum lineNum = new LineNum(bReader);
		LineSemi lineSemi = new LineSemi(lineNum);
		LineQuo lineQuo = new LineQuo(lineSemi);
		
		String line = null;
		while ((line = lineQuo.readLine()) != null) {
			System.out.println(line);
		}
	}
}
